LETUS online editor形式に変換してcopyするPopupMenu
2023-06-21
11:43:56 table記法を変換できるようにしようと思ったけど、このコードだと改修が大変だな テーブルの変換コードだけここに置いておこう
code:table.ts
const convertTable = (table: TableBlock): string => {
(cell) => cell.map(
(row) => row.map((node) => convertNode(node)).join("")
)
);
return `<table>
<caption>${table.fileName}</caption>
<thead>
<tr>
${head?.map?.((row) => <th>${row}</th>)?.join?.("\n") ?? ""}
<tr>
</thead>
<tbody>
${lines?.map?.(
(line) => <tr>\n${line.map((row) => <td>${row}</td>)}\n</tr>
)?.join?.("\n")
}
</tbody>
</table>`;
};
2023-06-07
17:47:02 raw URLを変換できるようにした
2023-02-06
21:47:55 iconをfont awesomeにした
2021-05-12
22:49:48 画像の幅を調節した
22:48:27 codeを変換できるようにした
2020-11-21 16:15:41
打ち消し線が反映されないバグを直した
~ではなく-だった
2020-11-12 01:28:50
見出しを<h4>から使うようにした
h4
h5
h6
2020-10-28 14:11:06
数式をインラインにした
2020-10-21 10:50:13
見出しを追加した
h1
h2
h3
2020-10-19 21:12:50
番号なしindentを実装した
行間を確保した
実装
簡略化のため、一段下げたら<li>になるようにした
[! ]を<code>に対応させた
問題とか
<img>に入れたstyleの一部は消えてしまうみたい
どうしようもないな
code blockに対応させたい
code:script.js
import {ScrapboxParser} from '/api/code/takker/scrapbox-parser.min.js/parser.js';
// markdown変換
scrapbox.PopupMenu.addButton({
title: "\uf13b",
onClick: text => {
const blocks = ScrapboxParser.parse(text, {hasTitle: false});
console.log('Parserd text:');
console.log(blocks);
if(navigator.clipboard){
const copiedText = convertSb2HTML(blocks).join('\n');
console.log(copiedText);
navigator.clipboard.writeText(copiedText).catch((e) => console.log(e));
console.log('Copied.');
}
return;
}
});
function convertSb2HTML(blocks) {
// このindent levelを基準にする
const topIndentLevel = Math.min(...blocks.map(block => block.indent));
let indentLevel = topIndentLevel;
for (const block of blocks.filter(block => block.type === 'line')) {
// 前loopからのindent levelの増減
const diff = block.indent - indentLevel;
// indent levelが減ったら</ul>を追加する
// indent levelが増えたら<ul>を追加する
if (diff > 0) result.push(......Array(diff).map(_ => '<ul style="margin-top: 5px;margin-bottom: 5px;">')); const content = block.nodes.map(node => convertNode(node)).join('');
if (block.indent > topIndentLevel) {
result.push(<li>${content}</li>);
} else {
result.push(${content}<br/>);
}
indentLevel = block.indent;
}
// </ul>の不足分を補う
result.push('</p>');
return result;
}
HTML要素を含んだ文字列を返す
そもそもtext editorにテキスト形式で貼り付けるという使用方法が前提になっている。わざわざDOMを生成する必要がない
code:script.js
function convertNode(node) {
switch (node.type) {
case 'quote':
// scrapboxのcssからパクった
return `<span style="
font-style: italic;
background-color: rgba(128,128,128,0.1);
display: block;
padding-left: 4px;">${node.nodes.map(node => convertNode(node)).join('')}</span>`;
case 'image':
case 'strongImage':
return <img src="${node.src}" style="max-width: 50vw;"/>;
case 'icon':
let src = '';
let href = '';
let alt = '';
switch(node.pathType) {
case 'root':
href = https://scrapbox.io${node.path};
src = https://scrapbox.io/api/pages/${node.path}/icon;
alt = node.path.replace(/^\/^\/+\/(.*)/,'$1'); break;
case 'relative':
href = https://scrapbox.io/${scrapbox.Project.name}/${node.path};
src = https://scrapbox.io/api/pages/${scrapbox.Project.name}/${node.path}/icon;
alt = node.path;
break;
}
return `<a target="_blank" href="${href}"><img style="
height: 1.3em;
vertical-align: top;" src="${src}" alt="${alt}" /></a>`;
case 'strongIcon':
return ''; //無視
case 'formula':
return \\( ${node.formula} \\);
case 'helpfeel':
return '';
case 'decoration':
let result = node.nodes.map(node => convertNode(node)).join('');
if (node.decos.includes('*-4')) result = <h4>${result}</h4>;
if (node.decos.includes('*-3')) result = <h5>${result}</h5>;
if (node.decos.includes('*-2')) result = <h6>${result}</h6>;
if (node.decos.includes('*-1')) result = <strong>${result}</strong>;
if (node.decos.includes('/')) result = <i>${result}</i>;
if (node.decos.includes('-')) result = <strike>${result}</strike>;
if (node.decos.includes('!')) result = <pre>${result}</pre>;
return result;
case 'strong':
return <strong>${node.nodes.map(node => convertNode(node)).join('')}</strong>;
case 'code':
return <code>${node.text}</code>
case 'commandLine':
case 'googleMap':
return ''; // 今回は無視
case 'blank':
return <span>${node.text}</span>;
case 'link':
switch(node.pathType) {
case 'root':
return <a target="_blank" href="https://scrapbox.io${node.href}">${node.href}</a>;
case 'relative':
return <a target="_blank" href="https://scrapbox.io/${scrapbox.Project.name}/${node.href}">${node.href}</a>;
case 'absolute':
return <a target="_blank" href="${node.href}">${node.content || node.href}</a>;
}
case 'hashTag':
return <a href="https://scrapbox.io/${scrapbox.Project.name}/${node.href}">#${node.href}</a>;
case 'plain':
return <span>${node.text}</span>;
}
}